﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using SelfMadeMillionaire.Core;
using SelfMadeMillionaire.Core.Entities;
using SelfMadeMillionaire.Core.Enums;
using SelfMadeMillionaire.Core.Repositories;
using SelfMadeMillionaire.Core.Services;
using SelfMadeMillionaire.Core.Specifications;

namespace SelfMadeMillionaire.BLL.Services
{
	public class NewsletterService : INewsletterService
	{
		private readonly IEmailMessageRepository _mailingListRepository;
		private readonly INewsletterRepository _newsletterRepository;
		private readonly ISchedulerService _schedulerService;

		public NewsletterService(INewsletterRepository newsletterRepository,
			IEmailMessageRepository mailingListRepository,
			ISchedulerService schedulerService)
		{
			_newsletterRepository = newsletterRepository;
			_mailingListRepository = mailingListRepository;
			_schedulerService = schedulerService;
		}

		public Newsletter Add(Newsletter newsletter)
		{
			newsletter.CreatedDate = DateTime.Now;
			newsletter.Status = (byte) StatusType.Active;
			return _newsletterRepository.Add(newsletter);
		}

		public Newsletter Update(Newsletter newsletter)
		{
			return _newsletterRepository.Update(newsletter);
		}

		public Newsletter Get(int id)
		{
			return _newsletterRepository.Get(id);
		}

		public IEnumerable<Newsletter> GetList(DateTime? startDate, DateTime? endDate, ProductType? product, byte? issueType,
            string symbols, string title, byte? minAccessLevel, byte? minAccessLevelAdmin, bool isAdmin)
		{
			IEnumerable<Newsletter> newsletters = _newsletterRepository.GetAll();

			return newsletters.Where(p => (p.Date >= (startDate.HasValue ? startDate : p.Date)) &&
			                              (p.Date < (endDate.HasValue ? endDate.Value.AddDays(1) : p.Date)) &&
			                              
                                          (
                                            (p.Letter == (product.HasValue ? (byte)product : p.Letter)) ||
                                            (p.Products.Any(x => x.ProductType == (product.HasValue ? (byte)product : x.ProductType)))
                                          ) &&

                                          (string.IsNullOrWhiteSpace(title) || p.Title.ToLower().Contains(title.ToLower())) &&
			                              (p.IssueType.ID == (issueType.HasValue ? issueType.Value : p.IssueType.ID)) &&
                                          (
                                            (
                                                (p.MinAccessLevel <= (minAccessLevel.HasValue ? minAccessLevel.Value : p.MinAccessLevel)) &&
                                                (p.MinAccessLevelOriginal == (minAccessLevelAdmin.HasValue ? minAccessLevelAdmin.Value : p.MinAccessLevelOriginal))
                                            )
                                            ||
                                            (p.Letter == (byte)ProductType.MaggiesMoneyMountain)
                                          ) &&
			                              (string.IsNullOrWhiteSpace(symbols) ||
                                           symbols.ToLower().Split(',')
                                               .Any(x => p.Symbols != null && p.Symbols.ToLower().Split(',').Any(s => s.ToLower().Contains(x.ToLower())))) &&
			                              (p.Status == (byte) StatusType.Active) &&
                                          ((!p.IsHide) || isAdmin)
                                          )
				.OrderByDescending(x => x.Date);
		}

		public IEnumerable<Newsletter> GetList(ISearchSpecification<Newsletter> specification)
		{
			return _newsletterRepository.GetList(specification).Where(x => !x.IsHide);
		}

        public IEnumerable<Newsletter> GetMmmRecentIssues()
        {
            return _newsletterRepository.GetAll()
                .Where(p => (p.Date >= DateTime.Now.AddDays(-5))
                    && (p.Status == (byte)StatusType.Active)
                    && (p.Letter == (byte)ProductType.MaggiesMoneyMountain)
                    && (!p.IsHide))
                .OrderByDescending(x => x.Date);
        }

		public void Remove(int id)
		{
			Newsletter newsletter = Get(id);
			newsletter.Status = (byte) StatusType.Deleted;
			Update(newsletter);
		}

        public void Hide(int id)
        {
            Newsletter newsletter = Get(id);
            newsletter.IsHide = true;
            Update(newsletter);
        }

        public void Show(int id)
        {
            Newsletter newsletter = Get(id);
            newsletter.IsHide = false;
            Update(newsletter);
        }

		public void Send(int id, string emailTemplate)
		{
			Newsletter newsletter = Get(id);

			string body = emailTemplate
				.Replace("[issueTypeName]", newsletter.IssueType.Title)
				.Replace("[currentYear]", DateTime.Now.Year.ToString(CultureInfo.InvariantCulture));

			//if (!string.IsNullOrWhiteSpace(newsletter.PdfFileName))
			//	body = FileLink.GetAbsoluteLinkOnFile(newsletter.PdfFileName);

            string subject = "{0}!";
            if(newsletter.Letter == (byte)ProductType.MaggiesMoneyMountain)
            {
                subject = "(Maggie Money Mountain) " + subject;
            }

			var message = new EmailMessage
			{
				Title = string.Format(subject, newsletter.IssueType.Title),
				Body = body, //newsletter.PdfFileName,
				ProductType = newsletter.Letter,
				MinAccessLevel = newsletter.MinAccessLevelOriginal
			};


            // для MMM новостей нет ограничений, всем отсылаем сразу же
            if (message.ProductType == (byte)ProductType.MaggiesMoneyMountain)
            {
                message.FreeSendDate = DateTime.Now;
                message.SilverSendDate = DateTime.Now;
                message.GoldSendDate = DateTime.Now;
                message.PlatinumSendDate = DateTime.Now;
            }
            else
            {
                if (newsletter.IssueType.Title == "Order Alert")
                {
                    SetSendPlatinumDate(newsletter, 0, message);
                }
                else if(newsletter.IssueType.Title == "Trade Alert")
                {
                    SetSendFreeDate(newsletter, 7, message);
                    SetSendSilverDate(newsletter, 2, message);
                    SetSendGoldDate(newsletter, 1, message);
                    SetSendPlatinumDate(newsletter, 0, message);
                }
                else if (newsletter.IssueType.Title == "Portfolio Update")
                {
                    SetSendFreeDate(newsletter, 7, message);
                    SetSendSilverDate(newsletter, 2, message);
                    SetSendGoldDate(newsletter, 1, message);
                    SetSendPlatinumDate(newsletter, 0, message);
                }
                else if (newsletter.IssueType.Title == "Stock Analysis")
                {
                    SetSendFreeDate(newsletter, 14, message);
                    SetSendSilverDate(newsletter, 7, message);
                    SetSendGoldDate(newsletter, 1, message);
                    SetSendPlatinumDate(newsletter, 0, message);
                }
                else if (newsletter.IssueType.Title == "Miscellaneous")
                {
                    SetSendFreeDate(newsletter, 7, message);
                    SetSendSilverDate(newsletter, 2, message);
                    SetSendGoldDate(newsletter, 1, message);
                    SetSendPlatinumDate(newsletter, 0, message);
                }
                else if (newsletter.IssueType.Title == "Year-End Update")
                {
                    SetSendFreeDate(newsletter, 7, message);
                    SetSendSilverDate(newsletter, 2, message);
                    SetSendGoldDate(newsletter, 1, message);
                    SetSendPlatinumDate(newsletter, 0, message);
                }
                else if (newsletter.IssueType.Title == "Portfolio Performance")
                {
                    SetSendFreeDate(newsletter, 7, message);
                    SetSendSilverDate(newsletter, 2, message);
                    SetSendGoldDate(newsletter, 1, message);
                    SetSendPlatinumDate(newsletter, 0, message);
                }
            }


			newsletter.EmailMessage = _mailingListRepository.Add(message);

			_newsletterRepository.Commit();
		}

        void SetSendFreeDate(Newsletter nl, int daysShift, EmailMessage em)
        {
            if (nl.MinAccessLevelOriginal <= (byte)SubscriptionType.Free)
            {
                em.FreeSendDate = DateTime.Now.AddDays(daysShift);
            }
        }

        void SetSendSilverDate(Newsletter nl, int daysShift, EmailMessage em)
        {
            if (nl.MinAccessLevelOriginal <= (byte)SubscriptionType.Silver)
            {
                em.SilverSendDate = DateTime.Now.AddDays(daysShift);
            }
        }

        void SetSendGoldDate(Newsletter nl, int daysShift, EmailMessage em)
        {
            if (nl.MinAccessLevelOriginal <= (byte)SubscriptionType.Gold)
            {
                em.GoldSendDate = DateTime.Now.AddDays(daysShift);
            }
        }

        void SetSendPlatinumDate(Newsletter nl, int daysShift, EmailMessage em)
        {
            if (nl.MinAccessLevelOriginal <= (byte)SubscriptionType.Platinum)
            {
                em.PlatinumSendDate = DateTime.Now;
            }
        }
        
		public IEnumerable<IssueType> GetIssueTypes()
		{
			return _newsletterRepository.GetIssueTypes();
		}
	}
}